<script>
     /*
                三、SQL Server 中常见的死锁具体原因

                        1、不同顺序的访问对象  (最常见)

                                场景：   事务A 先锁表X，再请求锁表Y；  同时，事务B先锁表Y，再请求锁表X。

                                原因：  访问相同一组对象，但顺序不一致，极易形成循环等待

                        2、缺失或不当的索引

                                场景：  一个事务执行全表扫描或范围扫描，锁定了大量行 (甚至升级为表锁)，另一个事事务恰好要更新其中某一行，或者请求一个兼容锁，导致阻塞和死锁。

                                原因：  没有合适的索引导致锁的颗粒度变大，增加了冲突的概率。

                        3、长时间运行的事务

                                场景：  一个事务长时间保持其锁 (例如，在事务中进行大量操作或等待用户输入)，其他事物不得不长时间等待，
                                
                                        在这期间，其他事务可能持有了这个等待事务所需要的资源，从而导致死锁。

                                原因：  锁持有的时间过长，增大了与其他事务放生冲突的时间窗口。

                        4、锁升级

                                场景：  SQL Server 为了节省内存，可能会将大量细颗粒度的 "行锁" 或 "页锁" 升级为 "表锁"。

                                        如果另一个事务已经持有了该表的某些行锁，或者正在请求该表的锁，就可能发生死锁。

                                原因：  锁颗粒度突然变大，意外地阻塞了更多请求。

                        5、读写并发与更新锁 (U锁)

                                场景：  
                                        <1>、事务 A 持有一个共享锁（S锁）读取某行。
                                    
                                        <2>、事务 B 也想更新该行，它请求一个排他锁（X锁）。由于 X锁与 S锁 不兼容，事务 B 被阻塞，进入等待队列。

                                        <3>、此时，如果事务 A 想要升级它的 S锁 为 X锁 以进行更新，它必须等待事务 B 释放其锁请求（尽管事务 B 是被阻塞的）。

                                                这就形成了循环等待：A 在等 B，B 在等 A。

                                原因：  SQL Server 使用更新锁（U锁） 来预防这种常见情况。U锁 与 S锁 兼容，但与另一个 U锁 或 X锁 不兼容。、

                                        事务在修改数据前会先申请 U锁，这样可以避免上述的转换死锁。
            */
</script>